﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using SuperiorModel;
using SuperiorCommon;
using SuperiorShopBussinessService;
using Redis;
using WxPayAPIMobileShopCode.Common.Helpers;
using System.Text;
using System.Net.Http;

namespace Api.SuperiorShop.Controllers
{
    [ApiException]
    public class OrderController : ApiControllerBase
    {
        // GET: Common
        private readonly IProductService _IProductService;
        private readonly ISetService _ISetService;
        private readonly IMarketingService _IMarketingService;
        private readonly IShopAppService _IShopAppService;
        private readonly IShopCartService _IShopCartService;
        private readonly IOrderService _IOrderService;

        public OrderController(IProductService IProductService, ISetService ISetService, IMarketingService IMarketingService, IShopAppService IShopAppService, IShopCartService IShopCartService, IOrderService IOrderService)
        {
            _IProductService = IProductService;
            _ISetService = ISetService;
            _IMarketingService = IMarketingService;
            _IShopAppService = IShopAppService;
            _IShopCartService = IShopCartService;
            _IOrderService = IOrderService;
        }
        protected override void Dispose(bool disposing)
        {
            this._IProductService.Dispose();
            this._ISetService.Dispose();
            this._IMarketingService.Dispose();
            this._IShopAppService.Dispose();
            this._IShopCartService.Dispose();
            this._IOrderService.Dispose();
            base.Dispose(disposing);
        }
        /// <summary>
        /// 获取订单详情
        /// </summary>
        /// <param name="OrderID"></param>
        /// <returns></returns>
        [HttpGet]
        public ApiResultModel<object> GetDetail(int OrderID)
        {
                //由于订单除了状态，都是静态数据。所有把静态数据，存进redis
                Func<Api_OrderDetail_InfoModel> fucc = delegate ()
                {
                    return _IOrderService.Api_GetDetail(OrderID);
                };
                var orderModel = DataIntegration.GetData<Api_OrderDetail_InfoModel>("GetDetail_" + OrderID, fucc,1);
                if (orderModel == null)
                    return Error("获取出错");
                if (string.IsNullOrEmpty(orderModel.OrderNo))
                {
                    RedisManager.Remove("GetDetail_" + OrderID);
                    return Error("获取异常");
                }
                //读取订单状态
                int orderstatus = _IOrderService.Api_GetOrderStatus(OrderID);
                orderModel.OrderStatus = orderstatus;
                return Success(orderModel);
        }
        /// <summary>
        /// 获取订单列表
        /// </summary>
        /// <param name="criteria"></param>
        /// <returns></returns>
        [HttpPost]
        public ApiResultModel<object> GetOrderList(Api_OrderListCriteria criteria)
        {
            if (string.IsNullOrEmpty(criteria.UserId) || string.IsNullOrEmpty(criteria.Spid))
                return Error("非法参数");
            var _spid = base.ValidataParms(criteria.Spid);
            if (_spid == null)
                return Error("非法参数");
            criteria.Spid = _spid;
            var _userid = base.ValidataParms(criteria.UserId);
            if (_userid == null)
                return Error("非法参数");
            criteria.UserId = _userid;
            var res = _IOrderService.Api_GetOrderList(criteria);
            return Success(res);
        }
        /// <summary>
        /// 申请售后
        /// </summary>
        /// <param name="orderid"></param>
        /// <param name="userid"></param>
        /// <returns></returns>
        [HttpGet]
        public ApiResultModel<object> ServiceOrder(int orderid, string userid)
        {
            var _userid = base.ValidataParms(userid);
            if (_userid == null)
                return Error("非法参数");
            var res = _IOrderService.Api_ServiceOrder(orderid,_userid.ToInt());
            if (!res)
                return Error("申请失败");
            return Success(true);
        }
        /// <summary>
        /// 创建订单
        /// </summary>
        /// <param name="criteria"></param>
        /// <returns></returns>
        [HttpPost]
        public ApiResultModel<object> CreateOrder_Cart(Api_CreateOrderCriteria criteria)
        {
            if (string.IsNullOrEmpty(criteria.Spid) || string.IsNullOrEmpty(criteria.Said) || string.IsNullOrEmpty(criteria.UserId) || criteria.ConsigneeId <= 0 || criteria.ShipAmount < 0 || criteria.Api_CreateOrder_ProductItems == null || criteria.Api_CreateOrder_ProductItems.Count <= 0)
                return Error("非法参数");
            var _spid = base.ValidataParms(criteria.Spid);
            if (_spid == null)
                return Error("非法参数");
            criteria.Spid = _spid;
            var _said = base.ValidataParms(criteria.Said);
            if (_said == null)
                return Error("非法参数");
            criteria.Said = _said;
            var _userid = base.ValidataParms(criteria.UserId);
            if (_userid == null)
                return Error("非法参数");
            criteria.UserId = _userid;
            Func<ShopAppModel> fucc = delegate ()
            {
                return _IShopAppService.GetShopAppModel(_spid.ToInt());
            };
            var shopAppModel = DataIntegration.GetData<ShopAppModel>("GetShopAppModel_" + _spid, fucc);
            if (shopAppModel == null)
                return Error("获取店铺模型出错");
            if (string.IsNullOrEmpty(shopAppModel.ShopAdminId))
            {
                RedisManager.Remove("GetShopAppModel_" + _spid);
                return Error("获取店铺信息出错");
            }
            if (criteria.AppType == 1)
            {
                if (shopAppModel.ProgrameIsExpire)
                    return Error("该商城已到期,不可下单");
            }
            else if (criteria.AppType == 2)
            {
                if (shopAppModel.H5IsExpire)
                    return Error("该商城已到期，不可下单");
            }
            foreach (var item in criteria.Api_CreateOrder_ProductItems)
            {
                var _productid = base.ValidataParms(item.ProductId);
                if (_productid == null)
                    return Error("非法参数");
                item.ProductId = _productid;
            }
            var skuids =  string.Join(",", criteria.Api_CreateOrder_ProductItems.Select(p => p.Product_SkuId.ToString()).ToArray());
            //获取需要检测的商品相关数据
            var checkList = _IProductService.Api_GetCreateOrder_CheckItemList(skuids);
            criteria.Api_CreateOrder_ProductItems.ForEach((item)=> {
                item.Api_CreaterOrder_CheckItem = checkList.Where(i => i.ProductSkuId == item.Product_SkuId).FirstOrDefault();
            });
            //验证SKU
            foreach (var item in criteria.Api_CreateOrder_ProductItems)
            {
                var _productName = item.Api_CreaterOrder_CheckItem.ProductName + " " + item.Api_CreaterOrder_CheckItem.ProppetyCombineName;
                if (item.SaleNum > item.Api_CreaterOrder_CheckItem.StockNum)
                    return Error("商品-"+_productName+" 库存不足");
                if (item.Api_CreaterOrder_CheckItem.IsDel == 1)
                    return Error("商品-"+_productName+" 已删除过期");
                if (item.Api_CreaterOrder_CheckItem.Product_OptionStatus != 1)
                    return Error("商品"+_productName+" 已下架或删除");
                if (item.Api_CreaterOrder_CheckItem.Product_IsDel == 1)
                    return Error("商品"+_productName+" 已删除");
            }
            //验证金额
            var _totalProductAmount = 0m;//商品总金额
            criteria.Api_CreateOrder_ProductItems.ForEach((item)=> {
                _totalProductAmount += item.SaleNum * item.Api_CreaterOrder_CheckItem.SallPrice;
            });
            var _couponAmount = 0.0m;
            if (criteria.CouponId > 0)
            {
                
                var couponModel = _IMarketingService.Api_GetUserCoupon(_userid.ToInt(),criteria.CouponId);
                if (couponModel.CouponId == 0)
                    return Error("非法参数");
                if (couponModel.CouponType == 1)
                {
                    //满减券
                    if (_totalProductAmount < couponModel.MinOrderAmount)
                        return Error("满减优惠券数据异常");
                    else
                        _couponAmount = couponModel.DelAmount;
                }
                else if (couponModel.CouponType == 2)
                {
                    //折扣券
                    _couponAmount =decimal.Round(((100 - couponModel.Discount) / 100m) * _totalProductAmount,2);
                    //测试如果是1分钱得话
                    if (_couponAmount < 0.01m)
                        _couponAmount = 0.01m;
                }
                _totalProductAmount -= _couponAmount;
            }
            var _totalAmount = _totalProductAmount + criteria.ShipAmount;
            if (_totalAmount != criteria.ToalAmount)
                return Error("计算金额非法");
            //临时将本地购物车数据，插入购物车表，在下单存储过程重读取
            if (!_IShopCartService.CreateOrderInsert(criteria))
                return Error("购物车数据异常");
            criteria.ProductAmount = _totalProductAmount;
            criteria.CouponAmount = _couponAmount;
            string msg = "";
            var res = _IOrderService.Program_CreateOrder_Cart(criteria, out msg);
            //如果是H5 ，相关支付参数从WEBCONFIG取
            if (criteria.AppType == 2)
            {
                res.Appid = ConfigSettings.Instance.APPID;
                res.Mch_id = ConfigSettings.Instance.Merchant_Id;
                res.Paykey = ConfigSettings.Instance.PaySecret;
            }
            res.AppType = criteria.AppType;
            if (msg != "")
                return Error(msg);
            if (res.OrderID == 0)
                return Error("Orderid异常");
            Api_CreateOrderResultModel resultmodel = new Api_CreateOrderResultModel();
            resultmodel.OrderID = res.OrderID;

            //微信统一下单
            WxPayData wxd = WeiXinCreateOrder(res);
            if (wxd == null)
                return Error("微信统一下单失败");

            var payParamater = new Api_OrderPayResultModel();
            payParamater.AppId = wxd.GetValue("appId").ToString();
            payParamater.TimeStamp = wxd.GetValue("timeStamp").ToString();
            payParamater.NonceStr = wxd.GetValue("nonceStr").ToString();
            payParamater.Package = wxd.GetValue("package").ToString();
            payParamater.SignType = wxd.GetValue("signType").ToString();
            payParamater.PaySign = wxd.GetValue("paySign").ToString();
            payParamater.Payorderno = wxd.GetValue("payorderno").ToString();
            payParamater.Orderno = wxd.GetValue("orderno").ToString();

            resultmodel.PayParamater = payParamater;

            //存储当前订单的拉起微信支付的模型
            RedisManager.Set<Api_CreateOrderResultModel>(payParamater.Orderno + _userid, resultmodel, DateTime.Now.AddMinutes(15));
            return Success(resultmodel);
        }

        private WxPayData WeiXinCreateOrder(Api_WeixinCreateOrderModel model)
        {
            LogManger.Instance.WriteLog("统一下单参数" + model.ToJson());
            string url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
            string notifyurl = "";
            if (model.AppType == 1) {
                notifyurl = ConfigSettings.Instance.WxCallBackUrl;
            } else if (model.AppType == 2)
            {
                notifyurl = ConfigSettings.Instance.WxCallBackUrl_H5;
            }
             
            string paykey = model.Paykey;
            string time_start = DateTime.Now.ToString("yyyyMMddHHmmss");
            string time_expire = DateTime.Now.AddMinutes(10).ToString("yyyyMMddHHmmss");
            //统一下单
            WxPayData data = new WxPayData();
            data.SetValue("appid", model.Appid);//公众账号ID
            data.SetValue("mch_id", model.Mch_id);//商户号
            data.SetValue("nonce_str", ToolManager.GenerateNonceStr());//随机字符串
            data.SetValue("body", "正在卖的商品");//商品描述
                                             //data.SetValue("attach", "test");//附加数据
            data.SetValue("out_trade_no", model.OrderNumber);//商户订单号
            data.SetValue("total_fee", (int)Math.Round(model.TotalFee * 100));//总金额 单位分
            data.SetValue("time_start", time_start);
            data.SetValue("time_expire", time_expire);
            //data.SetValue("goods_tag", "test");//商品标记 代金券或立减优惠功能的参数
            data.SetValue("trade_type", "JSAPI");
            data.SetValue("openid", model.Openid);
            data.SetValue("notify_url", notifyurl);//异步通知url
            data.SetValue("spbill_create_ip", "");//终端ip
            data.SetValue("sign", data.MakeSign(model.Paykey));
            string xml = data.ToXml();
            string response = WeiXinHelper.Post(xml, url, false, 10);

            LogManger.Instance.WriteLog("微信统一下单" + response);
            WxPayData result = new WxPayData();
            result.FromXml(response);
            //签名验证
            // 错误时没有签名
            if (result.IsSet("return_code") && result.GetValue("return_code").ToString() == "SUCCESS" && result.IsSet("sign") && result.GetValue("sign").ToString() != "")
            {
                //获取接收到的签名
                string return_sign = result.GetValue("sign").ToString();
                //在本地计算新的签名
                string cal_sign = result.MakeSign(paykey);
                if (cal_sign == return_sign)
                {
                    if (result.IsSet("appid") && result.IsSet("prepay_id") && result.GetValue("prepay_id").ToString() != "")
                    {
                        string prepay_id = result.GetValue("prepay_id").ToString();
                        WxPayData jsApiParam = new WxPayData();
                        jsApiParam.SetValue("appId", result.GetValue("appid"));
                        jsApiParam.SetValue("timeStamp", ToolManager.ConvertDateTimeInt(DateTime.Now));
                        jsApiParam.SetValue("nonceStr", ToolManager.GenerateNonceStr());
                        jsApiParam.SetValue("package", "prepay_id=" + prepay_id);
                        jsApiParam.SetValue("signType", "MD5");
                        jsApiParam.SetValue("paySign", jsApiParam.MakeSign(paykey));
                        //
                        //jsApiParam.SetValue("payorderno", prepay_id);
                        jsApiParam.SetValue("payorderno", model.OrderNumber);
                        jsApiParam.SetValue("orderno", model.OrderNumber);
                        return jsApiParam;
                    }
                    else
                    {
                        return null;
                    }
                }
                else
                {

                    LogManger.Instance.WriteLog("订单号：" + model.OrderNumber + ";接收到签名：" + return_sign + ";本地签名：" + cal_sign);
                    return null;
                }
            }
            else
            {
                if (result.IsSet("return_msg") && result.GetValue("return_msg").ToString() != "")
                {
                    LogManger.Instance.WriteLog("订单号：" + model.OrderNumber + ";微信支付预处理失败：" + result.GetValue("return_msg").ToString());
                    return null;
                }
                else
                {
                    return null;
                }
            }
        }
        private static object LockData = new object();
        [ApiExceptionAttribute]
        [HttpPost]
        public HttpResponseMessage WxCallBack()
        {
            //接收从微信后台POST过来的数据
            System.IO.Stream s = System.Web.HttpContext.Current.Request.InputStream;
            int count = 0;
            byte[] buffer = new byte[1024];
            StringBuilder builder = new StringBuilder();
            while ((count = s.Read(buffer, 0, 1024)) > 0)
            {
                builder.Append(Encoding.UTF8.GetString(buffer, 0, count));
            }
            s.Flush();
            s.Close();
            s.Dispose();
            LogManger.Instance.WriteLog("微信回调返回数据：" + builder.ToString());
            //转换数据格式并验证签名
            WxPayData data = new WxPayData();
            try
            {
                data.FromXml(builder.ToString());
                //2015-06-29 错误时没有签名
                if (data.IsSet("return_code") && data.GetValue("return_code").ToString() == "SUCCESS" && data.IsSet("sign") && data.GetValue("sign").ToString() != "")
                {
                    string appid = data.GetValue("appid").ToString();
                    string paykey = _IShopAppService.GetPayKeyByAppid(appid);
                    if (appid != null)
                    {
                        //获取接收到的签名
                        string return_sign = data.GetValue("sign").ToString();
                        //在本地计算新的签名
                        string cal_sign = data.MakeSign(paykey);
                        if (cal_sign == return_sign)
                        {
                            //更新订单状态
                            string out_trade_no = data.GetValue("out_trade_no").ToString();
                            //重复调用验证
                            lock (LockData)
                            {

                                if (RedisManager.Get<string>(out_trade_no) != null)
                                {
                                    LogManger.Instance.WriteLog("微信支付回调发生了频繁重复调用！订单号" + out_trade_no);
                                    return null;
                                }
                                else
                                {
                                    //将当前订单号写入缓存
                                    RedisManager.Set(out_trade_no, out_trade_no, DateTime.Now.AddMinutes(15));
                                }
                            }
                            string transaction_id = data.GetValue("transaction_id").ToString();
                            string result_code = data.GetValue("result_code").ToString();
                            string err_code = data.IsSet("err_code") ? data.GetValue("err_code").ToString() : string.Empty;
                            string time_end = data.GetValue("time_end").ToString();
                            float total_fee = 0; Int64 paytime; int status = 0;
                            float.TryParse(data.GetValue("total_fee").ToString(), out total_fee);
                            Int64.TryParse(time_end, out paytime);
                            if (result_code == "SUCCESS")
                            {
                                status = 1;
                            }
                            else if (result_code == "FAIL")
                            {
                                status = 2;
                            }
                            else
                            {
                                LogManger.Instance.WriteLog("微信回调业务结果错误返回信息：" + builder.ToString() + ";业务结果：" + result_code);
                            }
                            LogManger.Instance.WriteLog("out_trade_no：" + out_trade_no + ";status" + status+ "total_fee="+ (total_fee / 100));
                            if (status == 1 || status == 2)
                            {
                                //存储过程操作
                                var ret = _IOrderService.Program_WxNotice_Cart(out_trade_no, status, (total_fee / 100), transaction_id);
                                //记日志，参数，返回值
                                LogManger.Instance.WriteLog("微信回调更改状态返回"+ret);
                            }
                            WxPayData res = new WxPayData();
                            res.SetValue("return_code", "SUCCESS");
                            res.SetValue("return_msg", "OK");
                            return base.RetMessage(res.ToXml());

                        }
                        else
                        {
                            LogManger.Instance.WriteLog("微信回调签名认证失败返回信息：" + builder.ToString() + ";接收到签名：" + return_sign + ";本地签名：" + cal_sign);
                            WxPayData res = new WxPayData();
                            res.SetValue("return_code", "FAIL");
                            res.SetValue("return_msg", "签名失败");
                            return base.RetMessage(res.ToXml());
                        }
                    }
                    else
                    {
                        //SystemLog.WriteFile("微信回调获取商户信息失败返回信息：" + builder.ToString());
                        WxPayData res = new WxPayData();
                        res.SetValue("return_code", "FAIL");
                        res.SetValue("return_msg", "商户不存在");
                        return base.RetMessage(res.ToXml());
                    }
                }
                else
                {
                    //SystemLog.WriteFile("微信回调返回失败返回信息：" + builder.ToString());
                    WxPayData res = new WxPayData();
                    res.SetValue("return_code", "FAIL");
                    res.SetValue("return_msg", "参数格式校验错误");
                    return base.RetMessage(res.ToXml());
                }
            }
            catch (Exception ex)
            {
                LogManger.Instance.WriteLog("微信回调异常，返回内容：" + builder.ToString() + ";异常信息：" + ex.Message + ";异常堆栈：" + ex.StackTrace);
                WxPayData res = new WxPayData();
                res.SetValue("return_code", "FAIL");
                res.SetValue("return_msg", "回调数据异常");
                return base.RetMessage(res.ToXml());
            }
            finally
            {

            }
        }

        private static object LockData_H5 = new object();
        [ApiExceptionAttribute]
        [HttpPost]
        public HttpResponseMessage WxCallBack_H5()
        {
            //接收从微信后台POST过来的数据
            System.IO.Stream s = System.Web.HttpContext.Current.Request.InputStream;
            int count = 0;
            byte[] buffer = new byte[1024];
            StringBuilder builder = new StringBuilder();
            while ((count = s.Read(buffer, 0, 1024)) > 0)
            {
                builder.Append(Encoding.UTF8.GetString(buffer, 0, count));
            }
            s.Flush();
            s.Close();
            s.Dispose();
            LogManger.Instance.WriteLog("微信回调返回数据：" + builder.ToString());
            //转换数据格式并验证签名
            WxPayData data = new WxPayData();
            try
            {
                data.FromXml(builder.ToString());
                //2015-06-29 错误时没有签名
                if (data.IsSet("return_code") && data.GetValue("return_code").ToString() == "SUCCESS" && data.IsSet("sign") && data.GetValue("sign").ToString() != "")
                {
                    string appid = data.GetValue("appid").ToString();
                    string paykey = ConfigSettings.Instance.PaySecret;
                    if (appid != null)
                    {
                        //获取接收到的签名
                        string return_sign = data.GetValue("sign").ToString();
                        //在本地计算新的签名
                        string cal_sign = data.MakeSign(paykey);
                        if (cal_sign == return_sign)
                        {
                            //更新订单状态
                            string out_trade_no = data.GetValue("out_trade_no").ToString();
                            //重复调用验证
                            lock (LockData_H5)
                            {

                                if (RedisManager.Get<string>(out_trade_no) != null)
                                {
                                    LogManger.Instance.WriteLog("微信支付回调发生了频繁重复调用！订单号" + out_trade_no);
                                    return null;
                                }
                                else
                                {
                                    //将当前订单号写入缓存
                                    RedisManager.Set(out_trade_no, out_trade_no, DateTime.Now.AddMinutes(15));
                                }
                            }
                            string transaction_id = data.GetValue("transaction_id").ToString();
                            string result_code = data.GetValue("result_code").ToString();
                            string err_code = data.IsSet("err_code") ? data.GetValue("err_code").ToString() : string.Empty;
                            string time_end = data.GetValue("time_end").ToString();
                            float total_fee = 0; Int64 paytime; int status = 0;
                            float.TryParse(data.GetValue("total_fee").ToString(), out total_fee);
                            Int64.TryParse(time_end, out paytime);
                            if (result_code == "SUCCESS")
                            {
                                status = 1;
                            }
                            else if (result_code == "FAIL")
                            {
                                status = 2;
                            }
                            else
                            {
                                LogManger.Instance.WriteLog("微信回调业务结果错误返回信息：" + builder.ToString() + ";业务结果：" + result_code);
                            }
                            LogManger.Instance.WriteLog("out_trade_no：" + out_trade_no + ";status" + status + "total_fee=" + (total_fee / 100));
                            if (status == 1 || status == 2)
                            {
                                //存储过程操作
                                var ret = _IOrderService.Program_WxNotice_Cart(out_trade_no, status, (total_fee / 100), transaction_id);
                                //记日志，参数，返回值
                                LogManger.Instance.WriteLog("微信回调更改状态返回" + ret);
                            }
                            WxPayData res = new WxPayData();
                            res.SetValue("return_code", "SUCCESS");
                            res.SetValue("return_msg", "OK");
                            return base.RetMessage(res.ToXml());

                        }
                        else
                        {
                            LogManger.Instance.WriteLog("微信回调签名认证失败返回信息：" + builder.ToString() + ";接收到签名：" + return_sign + ";本地签名：" + cal_sign);
                            WxPayData res = new WxPayData();
                            res.SetValue("return_code", "FAIL");
                            res.SetValue("return_msg", "签名失败");
                            return base.RetMessage(res.ToXml());
                        }
                    }
                    else
                    {
                        //SystemLog.WriteFile("微信回调获取商户信息失败返回信息：" + builder.ToString());
                        WxPayData res = new WxPayData();
                        res.SetValue("return_code", "FAIL");
                        res.SetValue("return_msg", "商户不存在");
                        return base.RetMessage(res.ToXml());
                    }
                }
                else
                {
                    //SystemLog.WriteFile("微信回调返回失败返回信息：" + builder.ToString());
                    WxPayData res = new WxPayData();
                    res.SetValue("return_code", "FAIL");
                    res.SetValue("return_msg", "参数格式校验错误");
                    return base.RetMessage(res.ToXml());
                }
            }
            catch (Exception ex)
            {
                LogManger.Instance.WriteLog("微信回调异常，返回内容：" + builder.ToString() + ";异常信息：" + ex.Message + ";异常堆栈：" + ex.StackTrace);
                WxPayData res = new WxPayData();
                res.SetValue("return_code", "FAIL");
                res.SetValue("return_msg", "回调数据异常");
                return base.RetMessage(res.ToXml());
            }
            finally
            {

            }
        }

        [ApiException]
        [HttpGet]
        public ApiResultModel<object> GetPayData(string userid, string orderno)
        {
            if (string.IsNullOrEmpty(userid) || string.IsNullOrEmpty(orderno))
                return Error("非法参数");
            string _userid = base.ValidataParms(userid);
            if (_userid == null)
                return Error("用户异常");
            //从redis获取拉起支付所需的缓存数据
            var res = RedisManager.Get<Api_CreateOrderResultModel>(orderno + _userid);
            if (res == null)
                return Error("获取支付数据失败");
            return Success(res);
        }



        /// <summary>
        /// 计算运费
        /// </summary>
        /// <param name="criteria"></param>
        /// <returns></returns>
        [HttpPost]
        public ApiResultModel<object> CountShipAmount(Api_CountShipAmountCriteria criteria)
        {
            var _spid = base.ValidataParms(criteria.Spid);
            if (_spid == null)
                return Error("非法参数");
            criteria.Spid = _spid;
            Func<ShopAppModel> fucc = delegate ()
            {
                return _IShopAppService.GetShopAppModel(_spid.ToInt());
            };
            var shopAppModel = DataIntegration.GetData<ShopAppModel>("GetShopAppModel_" + _spid, fucc);
            if (shopAppModel == null)
                return Error("获取店铺模型出错");
            if (string.IsNullOrEmpty(shopAppModel.ShopAdminId))
            {
                RedisManager.Remove("GetShopAppModel_" + _spid);
                return Error("获取店铺信息出错");
            }
            var _userid = base.ValidataParms(criteria.UserId);
            if (_userid == null)
                return Error("非法参数");
            criteria.UserId = _userid;
            foreach (var item in criteria.Products)
            {
                var _productId = base.ValidataParms(item.ProductId);
                if (_productId == null)
                    return Error("非法参数");
                item.ProductId = _productId;
            }
            //取店铺的满额包邮设置模型
            var fullSetModel = _IMarketingService.GetSetModel(SecretClass.DecryptQueryString(shopAppModel.ShopAdminId).ToInt());
            //读取每个商品的运费模板模型，并赋值
            criteria.Products.ForEach((item)=>
            {
                item.ShippingTemplateModel = GetShipModel(item.ShippingTemplateId);
            });
            //检测是否有模板的配送省份，不包括收货人省份
            foreach (var item in criteria.Products)
            {
                if (!item.ShipAllProvinceIds.Contains(criteria.ProvinceCode))
                {
                    return Error("商品:"+item.ProductName+",不参与邮件,请联系店家！");

                }
            }
            var res = GetShipAmount(criteria, fullSetModel);
            return Success(res);


        }

        private ShippingTemplateModel GetShipModel(int id)
        {
            Func<ShippingTemplateModel> fucc = delegate ()
            {
                return _ISetService.GetShippingTemplateModel(id);
            };
            var res = DataIntegration.GetData<ShippingTemplateModel>("ShippingTemplateModel_" + id, fucc);
            return res;
        }
        private decimal GetShipAmount(Api_CountShipAmountCriteria criteria, FullSetModel fullSetModel)
        {
            if (fullSetModel.OptionStatus == 1)
            {
                //开启了满额包邮
                //是否满足金额
                if (fullSetModel.Amount <= criteria.TotalProductAmount)
                {
                    //配送地区是否在包邮范围
                    if (!fullSetModel.NotHasProvinceIdList.Contains(criteria.ProvinceCode))
                    {
                        //在包邮范围
                        //判断商品是否全部在包邮范围,如果都在范围，0运费返回，不都在，将包邮的商品从计算运费商品集合中删掉
                        if (IsExistProduct(fullSetModel.NotHasProductIdList, criteria.Products.Select(p => p.ProductId).ToList()))
                        {
                            //全部在包邮范围
                            return 0;
                        }
                        else
                        {
                            //部分结算商品在不包邮得商品中
                            //将包邮的商品从计算运费商品集合中删掉
                            var _tempList = new List<Api_CountShipItem>();
                            criteria.Products.ForEach((item) =>
                            {
                                if (fullSetModel.NotHasProductIdList.Contains(item.ProductId))
                                {
                                    _tempList.Add(item);
                                }
                            });
                            criteria.Products = _tempList;
                        }
                    }

                }
            }
            var _tml = new List<Api_CountShipItem>();
            //去掉模板包邮的商品，首重或者首件为0
            criteria.Products.ForEach((p)=> {
                //运费模板，根据发送地区不同有多个子模板，找出当前收货人地区的子模板
                var tm = p.ShippingTemplateModel.Items.Where(i => i.ProvinceIdList.Contains(criteria.ProvinceCode)).FirstOrDefault();
                if (tm.FirstAmount > 0)
                    _tml.Add(p);
            });
            criteria.Products = _tml;
            if (criteria.Products.Count == 0)//说明全部走的包邮模板
                return 0;

            //到了这一步，过滤了满额包邮情况，过滤了包邮模板商品，剩下的都是走运费模板，要计算了
            //算法：首重/首件最大值的模板的商品，先正常计算运费，剩下的模板的商品，只按照续件/续重计算，求和。
            var maxShipT = criteria.Products.OrderByDescending(p => p.CurrentShipItem.FirstAmount).FirstOrDefault();//找出运费子模板首最大的那个商品模型
            //取出走当前模板的商品模型
            var _maxProductList = criteria.Products.Where(p => p.ShippingTemplateId == maxShipT.ShippingTemplateId).ToList();
            //计算这个模板的商品集合一共的运费
            var maxProductShipAmount = CountAmount(_maxProductList, 1);
            var _otherProductList = criteria.Products.Where(p => p.ShippingTemplateId != maxShipT.ShippingTemplateId).ToList();
            if (_otherProductList.Count == 0)
                return maxProductShipAmount;
            var otherProductShipAmount = CountAmount(_otherProductList,2);
            return maxProductShipAmount + otherProductShipAmount;
        }

        private decimal CountAmount(List<Api_CountShipItem> list, int type)
        {
            var res = 0m;
            if (type == 1)
            {
                var ship = list[0].CurrentShipItem;
                //正常计算,先算首再算续
                //这里正常计算的，一定是同一个运费模板，单个计算，会导致续的费用变多，所以先求总重或者总件，一起计算
                if (list[0].ShippingTemplateModel.ChargType == 1)
                {
                    //按件数
                    
                    var totalCount = list.Sum(p => p.SaleNum);//求所有商品的总件数
                    if (totalCount > ship.FirstValue)
                    {
                        //超过首件数量了
                        res = ship.FirstAmount + Math.Ceiling((totalCount - ship.FirstValue) / decimal.Parse(ship.NextValue.ToString())) * ship.NextAmount;
                    }
                    else
                    {
                        res = ship.FirstAmount;
                    }
                }
                else if (list[0].ShippingTemplateModel.ChargType == 2)
                {
                    //按重量
                    var totalWeight = list.Sum(p => p.SaleNum * p.Weight);//求总重量
                    if (totalWeight > ship.FirstValue)
                    {
                        res = ship.FirstAmount + Math.Ceiling(Convert.ToDecimal((totalWeight - ship.FirstValue)) / ship.NextValue) *  ship.NextAmount;
                    }
                    else
                    {
                        res = ship.FirstAmount;
                    }

                }
            }
            else
            {
                //只计算续。
                //先根据模板ID分组，循环组
                IEnumerable<IGrouping<int, Api_CountShipItem>> pGroup = list.GroupBy(p => p.ShippingTemplateId);
                foreach (var ps in pGroup)
                {
                    var _products = ps.ToList();
                    var _ship = _products[0].CurrentShipItem;
                    if (_products[0].ShippingTemplateModel.ChargType == 1)
                    {
                        //按件数
                        var _totalCount = _products.Sum(p => p.SaleNum);//求所有商品的总件数
                            //超过首件数量了
                            res +=Math.Ceiling(_totalCount / decimal.Parse(_ship.NextValue.ToString())) * _ship.NextAmount; 
                    }
                    else
                    {
                        //按重量
                        var _totalWeight = _products.Sum(p => p.SaleNum * p.Weight);//求总重量
                            res += Math.Ceiling(Convert.ToDecimal(_totalWeight) / _ship.NextValue) * _ship.NextAmount;
                      
                    }
                
                }
            }
            return res;
        }

        

        /// <summary>
        /// 判断商品是否全部在包邮范围
        /// </summary>
        /// <param name="list1">满额包邮不参与得商品集合</param>
        /// <param name="list2">结算商品集合</param>
        /// <returns></returns>
        private bool IsExistProduct(List<string> list1, List<string> list2)
        {
            var result = true;
            foreach (var item in list2)
            {
                if (list1.Contains(item))
                {
                    result = false;
                    break;
                }
            }
            return result;
        }
    }
}